<template>
  <base-container>
    <!-- 搜索栏 -->
    <avue-table-search
      :option="searchOption"
      v-model="searchParams"
      @search-change="loadTableSearch"
      @search-reset="loadTableSearchReset"
    />
    <!-- 卡片容器 -->
    <base-table-card>
      <template #header-right>
        <el-button type="primary" v-auth="[PERMS.OPE_MENU.ADD]" @click="handleOpenAddDialog">新增菜单</el-button>
      </template>
      <avue-crud
        ref="avueCrudRef"
        :option="tableOption"
        :data="tableData"
        v-model="formData"
        :page="page"
        :table-loading="tableLoading"
        @refresh-change="loadGetTableData"
        @current-change="loadTablePageChange"
        @size-change="loadTablePageSizeChange"
        @row-save="loadAdd"
        @row-update="loadEdit"
      >
        <template #icon-form>
          <icon-selector v-model="formData.icon" />
        </template>
        <template #activeIcon-form>
          <icon-selector v-model="formData.activeIcon" />
        </template>
        <template #name="{ row }">
          <div class="icon-container">
            <!-- 解决一级路由，图标展开占位 -->
            <div
              class="icon-container-expand"
              v-if="row.parentId === 0 && (!row.children || !row.children.length)"
            ></div>
            <base-icon class="mr8px" :name="row.icon || ''" :size="18" />
            <span>{{ row.name }}</span>
          </div>
        </template>
        <template #status="{ row }">
          <el-switch
            :model-value="row.status"
            :loading="row.statusLoading"
            :active-value="1"
            :inactive-value="0"
            :disabled="!hasStatusAuth"
            :before-change="() => handleStatusBeforeChange(row)"
          />
        </template>
        <template #menu="{ row }">
          <el-button type="primary" text v-auth="[PERMS.OPE_MENU.UPDATE]" @click="handleOpenEditDialog(row)">
            编辑
          </el-button>
          <el-button
            type="primary"
            text
            v-auth="[PERMS.OPE_MENU.ADD]"
            :disabled="row.category === 4"
            @click="handleOpenAddDialog(row)"
          >
            新增
          </el-button>
          <el-button type="info" text v-auth="[PERMS.OPE_MENU.DELETE]" @click="loadDel(row)">删除</el-button>
        </template>
      </avue-crud>
    </base-table-card>
  </base-container>
</template>

<script setup>
  import Option from "@/crudOption/menu/menu-list/menu";
  import { rent_qyz_ope as ComponentPath } from "virtual:app-routes-collection"; // 获取 Boss 端所有路由组件
  import IconSelector from "@/components/IconSelector/index.vue";

  // 获取全局方法
  const App = useGlobals();

  /**
   * 路由配置规则
   * 1. 目录（category = 1）只能配置菜单名称、路由地址、菜单图标、激活图标、菜单排序、路由定向、是否显示、菜单状态
   * 2. 菜单（category = 2）目录有的配置项，菜单都有，额外包含组件路径、路由名称、页面缓存、是否固定、
   * 3. 按钮（category = 3）只能配置菜单名称、菜单排序、菜单状态、应用编码、权限标识
   * 4. 目录级别菜单（category = 1）并且是一级菜单（parentId = 0）时，菜单图标（icon）和激活图标（activeIcon）为必填项。
   * 5. 目录级别菜单（category = 1）提交时，组件（component）字段值默认为 Layout。
   * 6. componentName 不允许重复
   */

  const PLATFORM = 2; // 1 = BOSS端，2 = 运管端，3 = 商管端

  onMounted(() => {
    // 获取表格数据
    loadGetTableData();
  });

  // avue-crud 组件实例
  const avueCrudRef = ref({});

  // 增删改查 hook
  let {
    data: tableData,
    loading: tableLoading,
    page: page,
    search: searchParams,
    form: formData,
    get: loadGetTableData,
    add: loadAdd,
    edit: loadEdit,
    del: loadDel,
    pageNumChange: loadTablePageChange,
    pageSizeChange: loadTablePageSizeChange,
    searchReset: loadTableSearchReset,
    searchChange: loadTableSearch,
  } = useCrudHook({
    get: Api.menu.GetMenuList,
    add: Api.menu.AddMenu,
    edit: Api.menu.UpdateMenu,
    del: Api.menu.DeleteMenu,
    dataRes: "data",
    delConfirm: {
      title: "提示",
      content: "确定删除该菜单及下级所有数据吗？",
      type: "warning",
    },
    getParamsFormat: params => ({ ...params, platform: PLATFORM }),
    editParamsFormat: row => {
      if (row.category === 1) {
        row.component = "Layout";
      } else if (row.category === 3) {
        row.component = "";
      }
      return { ...row, platform: PLATFORM };
    },
    addParamsFormat: row => {
      if (row.category === 1) {
        row.component = "Layout";
      } else if (row.category === 3) {
        row.component = "";
      }
      return { ...row, platform: PLATFORM };
    },
  });

  // 获取 搜索配置 和 表格配置
  const { searchOption, tableOption } = Option(formData);

  // 打开新增弹窗
  const handleOpenAddDialog = (row = {}) => {
    // 目录下，默认选择菜单类型
    if (row.category === 1) formData.value.category = 2;
    // 菜单下，默认选择按钮类型
    if (row.category === 2) formData.value.category = 4;
    // Tab栏下，默认选择按钮类型
    if (row.category === 3) formData.value.category = 4;
    // 设置父级菜单
    formData.value.parentId = row.id || 0;
    // 打开新增弹窗
    avueCrudRef.value.rowAdd();
  };

  // 打开编辑弹窗
  const handleOpenEditDialog = row => {
    avueCrudRef.value.rowEdit(row);
  };

  // 监听 tableData，转换成树形结构，并赋值给树形选择器
  watch(
    () => tableData.value,
    menu => {
      Api.menu.GetMenuTree({ platform: PLATFORM }).then(res => {
        const column = tableOption.value?.group?.[0]?.column;
        if (menu && menu.length && column?.parentId) {
          column.parentId.dicData = [{ label: "顶级菜单", value: 0 }, ...handleFormatTreeMenu(res.data || [])];
        } else if (tableOption.value?.group?.[0]?.column?.parentId) {
          column.parentId.dicData = [{ label: "顶级菜单", value: 0 }];
        }
      });
    },
    { immediate: true }
  );

  /**
   * 格式化树形菜单，过滤掉所有按钮类型，按钮类型不能作为父级菜单
   * @params { Array } menu 菜单列表
   * @returns { Array } 树形菜单
   */
  const handleFormatTreeMenu = menu => {
    const treeMenu = [];
    menu.forEach(item => {
      if (item.category === 4) return; // 过滤掉按钮类型
      const newItem = { label: item.name, value: item.id, category: item.category };
      if (item.children && item.children.length) {
        newItem.children = handleFormatTreeMenu(item.children);
      }
      treeMenu.push(newItem);
    });
    return treeMenu;
  };

  // 获取 userStore
  const userInfoStore = useUserInfoStore();

  // 是否有停用/启用权限
  const hasStatusAuth = computed(() => userInfoStore.hasAuth([PERMS.OPE_MENU.ENABLE]));

  // 菜单状态启用/禁用切换
  const handleStatusBeforeChange = row => {
    return new Promise((resolve, reject) => {
      App.$confirm(`是否${row.status === 1 ? "停用" : "启用"}该菜单？`, "提示", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      })
        .then(() => {
          const status = row.status === 1 ? 0 : 1; // 先取反
          row.statusLoading = true;
          Api.menu
            .StatusEnableChange({ id: row.id, status: status, platform: PLATFORM })
            .then(() => {
              // 操作结果
              $msg.success(status ? "启用成功" : "禁用成功");
              // 刷新状态数据
              row.status = status;
              // 操作成功，切换状态
              resolve(true);
            })
            .catch(() => {
              // 操作失败，保持原状态
              reject(false);
            })
            .finally(() => {
              row.statusLoading = false;
            });
        })
        .catch(() => {
          // 取消操作，保持原状态
          reject(false);
        });
    });
  };

  // 设置组件选择器的选项数据
  if (tableOption.value?.group?.[0]?.column?.component) {
    tableOption.value.group[0].column.component.dicData = ComponentPath;
  }

  // 监听权限变化，更新操作栏是否显示
  tableOption.value.menu = computed(() =>
    userInfoStore.hasAuth([PERMS.OPE_MENU.ADD, PERMS.OPE_MENU.UPDATE, PERMS.OPE_MENU.DELETE])
  );
</script>
<style lang="scss" scoped>
  // 选择表格第一列的所有单元格 (td)
  :deep(.el-table__row td:first-child) {
    // 展开图标处理
    .cell {
      display: flex;
      flex-wrap: nowrap;
      align-items: center;

      .icon-container {
        display: flex;
        flex-wrap: nowrap;
        align-items: center;

        .icon-container-expand {
          width: 16px;
          height: 16px;
          margin-right: 16px;
        }
      }

      // 解决二级路由，文字对齐问题
      .el-table__placeholder {
        margin-right: 12px;
      }

      // 自定义展开图标（未展开）
      .el-table__expand-icon {
        position: relative;
        display: block;
        width: 16px;
        height: 16px;
        margin-right: 16px;
        font-family: var(--iconfont-family);

        .el-icon {
          display: none;
        }

        &::before {
          content: "\e82f";
          width: 12px;
          height: 12px;
          display: flex;
          justify-content: center;
          align-items: center;
          padding: 1px;
          border: 1px solid var(--cb1);
          background-color: var(--fl1);
          border-radius: 2px;
        }
      }

      // 自定义展开图标（已展开）
      .el-table__expand-icon--expanded {
        transform: rotate(90deg);

        &::before {
          content: "\e830";
          transform: rotate(-90deg);
        }
      }
    }
  }
</style>
